package tr.edu.metu.is.mega.client.course.instructor.students;

import java.util.ArrayList;
import java.util.List;

import tr.edu.metu.is.mega.client.core.AsyncCallbackAdapter;
import tr.edu.metu.is.mega.client.core.DialogCallbackAdapter;
import tr.edu.metu.is.mega.client.core.MegaUtil;
import tr.edu.metu.is.mega.client.core.event.SelectionEventBus;
import tr.edu.metu.is.mega.client.core.event.SelectionEventListener;
import tr.edu.metu.is.mega.client.course.CourseChangeEvent;
import tr.edu.metu.is.mega.client.resource.MEGAIconBundle;
import tr.edu.metu.is.mega.client.resource.MEGAResourceBundle;
import tr.edu.metu.is.mega.client.resource.MEGAResources;
import tr.edu.metu.is.mega.client.service.GwtCourseService;
import tr.edu.metu.is.mega.client.service.GwtCourseServiceAsync;
import tr.edu.metu.is.mega.common.dto.CourseDTO;
import tr.edu.metu.is.mega.common.dto.TeamDTO;

import com.extjs.gxt.ui.client.Style.SortDir;
import com.extjs.gxt.ui.client.data.BeanModel;
import com.extjs.gxt.ui.client.data.BeanModelFactory;
import com.extjs.gxt.ui.client.data.BeanModelLookup;
import com.extjs.gxt.ui.client.event.ButtonEvent;
import com.extjs.gxt.ui.client.event.SelectionChangedEvent;
import com.extjs.gxt.ui.client.event.SelectionChangedListener;
import com.extjs.gxt.ui.client.event.SelectionListener;
import com.extjs.gxt.ui.client.store.ListStore;
import com.extjs.gxt.ui.client.widget.ContentPanel;
import com.extjs.gxt.ui.client.widget.Info;
import com.extjs.gxt.ui.client.widget.LayoutContainer;
import com.extjs.gxt.ui.client.widget.button.Button;
import com.extjs.gxt.ui.client.widget.form.FieldSet;
import com.extjs.gxt.ui.client.widget.grid.ColumnConfig;
import com.extjs.gxt.ui.client.widget.grid.ColumnModel;
import com.extjs.gxt.ui.client.widget.grid.Grid;
import com.extjs.gxt.ui.client.widget.layout.FillLayout;
import com.extjs.gxt.ui.client.widget.layout.FitLayout;
import com.extjs.gxt.ui.client.widget.toolbar.ToolBar;
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.ui.AbstractImagePrototype;

/**
 * Window for defining and changing team records.
 */
public class TeamManagementPanel extends LayoutContainer {

    private MEGAResourceBundle resourceBundle;

    private MEGAIconBundle iconBundle;

    private Grid<BeanModel> grid;

    private BeanModelFactory beanModelFactory;

    protected CourseDTO course;

    private final boolean selectAction;

    /**
     * Default constructor.
     */
    public TeamManagementPanel() {
        this(null, false);
    }

    /**
     * Alternative constructor.
     * 
     * @param courseDTO selected course.
     * @param select action true to fire selection event.
     */
    public TeamManagementPanel(CourseDTO courseDTO, boolean selectAction) {
        this.selectAction = selectAction;
        course = courseDTO;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    protected void onRender(Element parent, int index) {
        super.onRender(parent, index);
        setLayout(new FitLayout());
        resourceBundle = MEGAResources.RESOURCEBUNDLE;
        iconBundle = MEGAResources.ICONBUNDLE;
        beanModelFactory = BeanModelLookup.get().getFactory(TeamDTO.class);

        FieldSet set = new FieldSet();
        set.setHeight(200);
        set.setLayout(new FillLayout());
        set.setHeading(resourceBundle.teamManagementHeading());

        ContentPanel panel = new ContentPanel();
        panel.setHeaderVisible(false);

        panel.add(getGrid());
        if (!selectAction) {
            panel.setTopComponent(getToolBar());
        }

        set.add(panel);
        add(set);
        if (course != null && course.getTeams() != null) {
            setTeams(course.getTeams());
        }
        SelectionEventBus.getInstance().registerListener(CourseChangeEvent.Update.class, new SelectionEventListener<CourseDTO>() {

            @Override
            public void selectionChanged(CourseDTO selectedObject) {
                course = selectedObject;
                if (selectedObject.getTeams() != null) {
                    setTeams(selectedObject.getTeams());
                }
            }
        });
    }

    /**
     * Initializes and returns toolbar.
     * 
     * @return toolbar
     */
    private ToolBar getToolBar() {
        ToolBar toolBar = new ToolBar();
        toolBar.setMinButtonWidth(70);
        toolBar.setSpacing(5);

        Button addButton = new Button(resourceBundle.add(), AbstractImagePrototype.create(iconBundle.add()));
        addButton.addSelectionListener(new SelectionListener<ButtonEvent>() {

            @Override
            public void componentSelected(ButtonEvent ce) {
                TeamDTO dto = new TeamDTO(course);
                TeamEditDialog dialog = new TeamEditDialog(course);
                dialog.create(dto, new DialogCallbackAdapter<TeamDTO>() {

                    @Override
                    public void onOk(TeamDTO param) {
                        course.getTeams().add(param);
                        getService().updateCourse(course, new AsyncCallbackAdapter<CourseDTO>() {

                            @Override
                            public void onSuccess(CourseDTO result) {
                                SelectionEventBus.getInstance().fireEvent(CourseChangeEvent.UPDATE, result);
                            }
                        });
                    }
                });
            }
        });

        Button updateButton = new Button(resourceBundle.update(), AbstractImagePrototype.create(iconBundle.update()));
        updateButton.addSelectionListener(new SelectionListener<ButtonEvent>() {

            @Override
            public void componentSelected(ButtonEvent ce) {
                if (grid.getSelectionModel().getSelectedItem() != null) {
                    TeamEditDialog dialog = new TeamEditDialog(course);
                    final int in = course.getTeams().indexOf(grid.getSelectionModel().getSelectedItem().getBean());
                    Info.display("", "" + in);
                    dialog.update((TeamDTO) grid.getSelectionModel().getSelectedItem().getBean(), new DialogCallbackAdapter<TeamDTO>() {

                        @Override
                        public void onOk(TeamDTO param) {
                            course.getTeams().set(in, param);
                            getService().updateCourse(course, new AsyncCallbackAdapter<CourseDTO>() {

                                @Override
                                public void onSuccess(CourseDTO result) {
                                    SelectionEventBus.getInstance().fireEvent(CourseChangeEvent.UPDATE, result);
                                }
                            });

                        }
                    });
                }
            }
        });

        Button deleteButton = new Button(resourceBundle.delete(), AbstractImagePrototype.create(iconBundle.delete()));
        deleteButton.addSelectionListener(new SelectionListener<ButtonEvent>() {

            @Override
            public void componentSelected(ButtonEvent ce) {
                if (grid.getSelectionModel().getSelectedItem() != null) {
                    final int in = course.getTeams().indexOf(grid.getSelectionModel().getSelectedItem().getBean());
                    Info.display("", "" + in);
                    course.getTeams().remove(in);
                    getService().updateCourse(course, new AsyncCallbackAdapter<CourseDTO>() {

                        @Override
                        public void onSuccess(CourseDTO result) {
                            SelectionEventBus.getInstance().fireEvent(CourseChangeEvent.UPDATE, result);
                        }
                    });
                }
            }
        });
        toolBar.add(addButton);
        toolBar.add(updateButton);
        toolBar.add(deleteButton);

        return toolBar;
    }

    /**
     * Returns activity grid.
     * 
     * @return grid
     */
    private Grid<BeanModel> getGrid() {
        if (grid == null) {

            ListStore<BeanModel> store = new ListStore<BeanModel>();
            store.setDefaultSort(TeamDTO.FIELD_TEAM_NAME, SortDir.ASC);

            List<ColumnConfig> columns = new ArrayList<ColumnConfig>();
            columns.add(new ColumnConfig(TeamDTO.FIELD_TEAM_NAME, resourceBundle.teamManagementTeamName(), 50));
            columns.add(new ColumnConfig(TeamDTO.FIELD_MEMBERS_LIST, resourceBundle.teamManagementTeamMembers(), 150));

            ColumnModel cm = new ColumnModel(columns);

            grid = new Grid<BeanModel>(store, cm);
            if (!selectAction) {
                grid.getSelectionModel().addSelectionChangedListener(new SelectionChangedListener<BeanModel>() {

                    @Override
                    public void selectionChanged(SelectionChangedEvent<BeanModel> se) {
                        if (se.getSelectedItem() != null) {
                            SelectionEventBus.getInstance().fireEvent(CourseChangeEvent.TEAMSELECTED, (TeamDTO) se.getSelectedItem().getBean());
                        }
                    }
                });
            }

            MegaUtil.decoradeGridViewWithAutoHeight(grid, true);

        }
        return grid;
    }

    /**
     * Adds lecture notes to grid
     * 
     * @param lecture note list
     */
    public void setTeams(List<TeamDTO> teamList) {
        grid.getStore().removeAll();
        for (TeamDTO team : teamList) {
            grid.getStore().add(beanModelFactory.createModel(team));
        }
        grid.getStore().sort(TeamDTO.FIELD_TEAM_NAME, SortDir.ASC);
    }

    /**
     * Gets lecture notes from grid.
     * 
     * @return list of lecture notes
     */
    public List<TeamDTO> getTeams() {
        List<TeamDTO> teams = new ArrayList<TeamDTO>(grid.getStore().getModels().size());
        for (BeanModel model : grid.getStore().getModels()) {
            teams.add((TeamDTO) model.getBean());
        }
        return teams;
    }

    /**
     * Returns GWT course service instance.
     * 
     * @return service
     */
    public static GwtCourseServiceAsync getService() {
        return GwtCourseService.Util.getInstance();
    }

    /**
     * @return
     */
    public List<TeamDTO> getSelectedItems() {
        return MegaUtil.getSelectedItems(grid.getSelectionModel());
    }

}
